{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "73bd968b-d970-4a05-94ef-4e7abf990827",
   "metadata": {},
   "source": [
    "Chapter 02\n",
    "\n",
    "# 矩阵乘法两个视角\n",
    "Book_3《数学要素》 | 鸢尾花书：从加减乘除到机器学习 (第二版)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3833b4db-96e7-4dc3-9505-47e18c676df9",
   "metadata": {},
   "source": [
    "该代码使用`numpy`生成两个随机矩阵$A$和$B$并计算其矩阵乘积$C$，然后用`seaborn`绘制矩阵热图以可视化矩阵乘法的几何含义。矩阵$A$的维度为$m \\times p$，矩阵$B$的维度为$p \\times n$，其乘积$C = A \\times B$的维度为$m \\times n$。代码从两种视角展示了矩阵乘法的计算过程。\n",
    "\n",
    "### 代码细节\n",
    "\n",
    "1. **第一视角** - 矩阵整体乘法：\n",
    "   - 矩阵乘法$A \\times B = C$定义为将$A$的每一行与$B$的每一列进行点积，得到$C$中的每个元素。对于矩阵$C$的元素$C[i,j]$，计算公式为：\n",
    "\n",
    "     $$\n",
    "     C[i, j] = \\sum_{k=1}^{p} A[i, k] \\cdot B[k, j]\n",
    "     $$\n",
    "\n",
    "   - 使用热图分别展示矩阵$A$、$B$和$C$，使得乘法关系$A \\times B = C$清晰可见。\n",
    "\n",
    "2. **第二视角** - 分解矩阵乘法：\n",
    "   - 通过将$C$分解为$A$的每一列和$B$的对应行的外积之和展示矩阵乘法。设$A$的列向量和$B$的行向量分别为$A[:, k]$和$B[k, :]$，则可以将$C$分解为：\n",
    "\n",
    "     $$\n",
    "     C = C_1 + C_2 + \\dots + C_p\n",
    "     $$\n",
    "\n",
    "   - 其中每个$C_k$表示$A$的第$k$列与$B$的第$k$行的外积，计算公式为：\n",
    "\n",
    "     $$\n",
    "     C_k = A[:, k] \\times B[k, :]\n",
    "     $$\n",
    "\n",
    "   - 分别绘制出矩阵$C$的分量$C_1$、$C_2$和$C_3$（假设$p=3$），并展示出它们的逐项相加关系，即：\n",
    "\n",
    "     $$\n",
    "     C = C_1 + C_2 + C_3\n",
    "     $$\n",
    "\n",
    "### 总结\n",
    "\n",
    "该代码通过两种视角展示了矩阵乘法的几何过程，第一视角显示了矩阵的整体乘法关系，而第二视角则将矩阵乘法分解为逐列计算的外积累加。这种分解方式有助于理解矩阵乘法如何将行、列元素组合成新的矩阵。最终结果以热图形式显示，增强了对矩阵乘法结构的直观理解。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "39d8e979-e701-4dc0-a6cf-c58e3eb5a97b",
   "metadata": {},
   "source": [
    "## 导入库并设置随机种子"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "9d8d12c6-20c5-44d1-ac75-380d82610780",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from matplotlib import pyplot as plt\n",
    "import seaborn as sns\n",
    "\n",
    "np.random.seed(7)  # 设置随机种子以确保结果可重复"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "870a7f8b-2085-4c9c-9f4b-901e2257cda8",
   "metadata": {},
   "source": [
    "## 生成矩阵A和矩阵B"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "e4991b29-2ddb-476a-bcfe-3dbefe5e3ed6",
   "metadata": {},
   "outputs": [],
   "source": [
    "m = 6  # 矩阵A的行数\n",
    "p = 3  # 矩阵A的列数和矩阵B的行数\n",
    "n = 4  # 矩阵B的列数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "d91f425f-2ef4-444b-b7ed-e1955d473bff",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-8.47383421e-01,  5.59837584e-01, -1.23181537e-01],\n",
       "       [ 4.46930356e-01,  9.55979024e-01,  7.69917408e-02],\n",
       "       [ 2.24092732e-03, -8.55897733e-01, -4.63122040e-01],\n",
       "       [-2.34998349e-04,  3.58459992e-01,  6.07478072e-01],\n",
       "       [-2.38117734e-01, -8.68127306e-01, -4.23708801e-01],\n",
       "       [ 8.19187055e-01, -5.73229293e-01, -9.57520764e-02]])"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = np.random.uniform(-1, 1, m * p).reshape(m, p)  # 随机生成矩阵A\n",
    "A  # 输出矩阵A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "598efc50-99b6-46d3-acf2-b8d743e1f19f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.86241204, -0.95020154,  0.20109783,  0.900259  ],\n",
       "       [-0.53939424,  0.09697984,  0.81825675, -0.73366111],\n",
       "       [ 0.04682516,  0.50081972,  0.33802648, -0.06449428]])"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "B = np.random.uniform(-1, 1, p * n).reshape(p, n)  # 随机生成矩阵B\n",
    "B  # 输出矩阵B"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "86790661-5b75-4184-ba40-b54850df6a4e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-1.03853483,  0.79778625,  0.24604529, -1.16565111],\n",
       "       [-0.12660631, -0.29340424,  0.89813826, -0.30397708],\n",
       "       [ 0.44191315, -0.31707481, -0.85644097,  0.65982502],\n",
       "       [-0.16510866,  0.33922368,  0.49860873, -0.30237858],\n",
       "       [ 0.24306704, -0.07013273, -0.90146078,  0.4498704 ],\n",
       "       [ 1.01118975, -0.88193902, -0.33667873,  1.16421202]])"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "C = A @ B  # 计算矩阵A和矩阵B的乘积得到矩阵C\n",
    "C  # 输出矩阵C"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "3314be77-10bc-4cbf-958b-463043d7dad1",
   "metadata": {},
   "outputs": [],
   "source": [
    "all_max = 1  # 热图的最大显示值\n",
    "all_min = -1  # 热图的最小显示值"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4106a890-747c-48b8-8116-991524fc1e60",
   "metadata": {},
   "source": [
    "## 矩阵乘法的第一种视角"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "1af9a2eb-715e-4018-8164-e9ef459f702e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([0.5, 1.5, 2.5, 3.5, 4.5, 5.5]),\n",
       " [Text(0, 0.5, '1'),\n",
       "  Text(0, 1.5, '2'),\n",
       "  Text(0, 2.5, '3'),\n",
       "  Text(0, 3.5, '4'),\n",
       "  Text(0, 4.5, '5'),\n",
       "  Text(0, 5.5, '6')])"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA8QAAAEQCAYAAAB2nL3nAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAmLUlEQVR4nO3de3RU5d328WvPJBmOiQYNghxEqRyEcD7E4gGltBERaGtbtTTFHtQ3oBi1rMCq4KMYlCraB5tHfCyCFsEDCfoqVFpJqMs3AglZRrQiNRZtBVQghBQmycx+/wiMGRIwh5m9Z8/+ftaaNZk9e7gvZiX3/fvN3jNjmKZpCgAAAAAAl/HYHQAAAAAAADvQEAMAAAAAXImGGAAAAADgSjTEAAAAAABXoiEGAAAAALgSDTEAAAAAwJVoiAEAAAAArkRDDAAAAABwJRpiAAAAAIAr0RADAAAAAFyJhjjG7Nq1S4mJiTIMQ/v377c7DgAAAIAo2rZtm2bNmqULL7xQHTt2VJcuXTR27FgtWbJE1dXVdseLezTEMeb2229XfX29JKm8vNzeMIAF6uvrtXr1ak2ZMkVpaWlKSEhQ9+7dNXnyZK1evVqBQMDuiAAAAFGRm5ur8ePHa8+ePZo/f75ef/11rVmzRmPGjNF9992nxx9/3O6Icc8wTdO0OwQavPTSS7r++us1ZcoUvfbaa1qyZInmzZtndywgaioqKvSjH/1I+/fv16xZszR69Gj17t1bVVVVKikp0erVq3Xuuedq3bp1uuiii+yOCwAAEDGLFi3Sfffdp0WLFmnhwoVN7v/ggw9UU1Oj0aNH25DOPWiIY8SxY8c0aNAgBYNB7dy5U927d9f111+v559/3u5oQFTs2rVLl156qW688Ub97ne/U+fOnZvsc+zYMd15553auHGj3n77bZ1//vk2JAUAAIis0tJSjRs3TjNmzNCLL75odxxXoyGOESdfIVq7dq1+/OMfa9CgQZIaXhkC4k0gEFB6erq++93v6tFHH212H9M0FQwG5fV69bOf/UyHDh3Sq6++anFSAACAyJsxY4Y2bNigDz74QAMGDLA7jqvREMeAvXv3auDAgRo7dqyKiookST/+8Y/10ksvqbq6Wp06dbI3IBBhf/rTn7RgwQLt3r1bSUlJCgaDeuCBB/Tkk0/q4MGDuuaaazR+/Hi99tprKioq0ldffaVevXqpoqJC/fv3tzs+ACBCTNNs8WdFJCQkRDkNYI2amhqlpqZq/PjxKi4utjuO6/GhWjEgJydHtbW1+v3vfx/alp6ermAwqIqKChuTAdFRWFion//850pKSpIkLV++XA8//LDmzZun119/Xeeff75++9vfhvbv1q2bMjIytGXLFrsiAwCioLi4WImJiS26fPLJJ3bHBSJi165dqq2t1fDhw+2OAkm81GazLVu26OWXX1ZWVpb69Omjw4cPS5IuvPBCSQ2fND1u3DgbEwKRt3v3bt1www2h208++aRyc3N1++23S5ImTpyo9957T8FgMLRP9+7d9cUXX1ieFQAQPaNGjdL27dtbtG/Pnj2jnAawxsl6v0ePHvYGgSQaYlsFAoFQA7Bq1SqtWrWqyT589RLiUV1dnTp06BC6XVlZqZEjR4btM2bMGL3zzjuh25999pkmTpxoWUYAQPR16dKlxUfJOGUa8eK8886TJP3zn/+0OQkkTpm21RNPPKH33ntP9913n7Zs2dLkkpqaSkOMuNSnTx/t3r07dLt79+5NToWrrKwM/bx7925t27ZNkyZNsioiAMACnDINNxo6dKguvPBCvfDCCzpw4ECz+/z1r3+1OJV78aFaNvnyyy918cUXa9CgQXrrrbdkGEaTfa666ipt27ZNR44ckcfDaxeIH48++qheeOEFlZSUSJLmzZunNWvWaM2aNUpPT9err76qWbNmafz48br33nt1yy23aMaMGXrkkUdsTg4AiKTq6mp9+OGHLdo3PT099NkTgNO9+eabuuaaa5SWlqZ77rlHgwcPViAQUEVFhdatW6eOHTvygVsWoSG2yS233KI//vGP2rlzp4YMGdLsPnfeeacee+wx/f3vf+fj2BFXDh8+rIsuukiPPvqosrKydPToUc2cOVOFhYWSpG9961uaPn26li5dqu7du+uee+5RTk5Osy8cAQAAONF7772nJUuWaMuWLfriiy901llnqU+fPpo4caJuvPFGjRgxwu6IrkBDDMAWL730kmbOnKlVq1bpRz/6kSTpwIEDOnjwoAYMGKBDhw7p8OHD6tevH40wAAAAooKGGIBtnnvuOf3617/WVVddpV/96lcaO3aszj77bB06dEjbtm3TqlWrVF1drTfeeIOmGAAAABFHQwzAVpWVlXrwwQe1fv16HTx4MLS9R48euvHGG/Wb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",
      "text/plain": [
       "<Figure size 1200x300 with 8 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, axs = plt.subplots(1, 5, figsize=(12, 3))\n",
    "\n",
    "plt.sca(axs[0])\n",
    "ax = sns.heatmap(A, cmap='RdBu_r', vmax=all_max, vmin=all_min,\n",
    "                 cbar_kws={\"orientation\": \"horizontal\"},\n",
    "                 yticklabels=np.arange(1, m+1), xticklabels=np.arange(1, p+1))\n",
    "ax.set_aspect(\"equal\")\n",
    "plt.title('$A$')\n",
    "plt.yticks(rotation=0)\n",
    "\n",
    "plt.sca(axs[1])\n",
    "plt.title('$@$')\n",
    "plt.axis('off')\n",
    "\n",
    "plt.sca(axs[2])\n",
    "ax = sns.heatmap(B, cmap='RdBu_r', vmax=all_max, vmin=all_min,\n",
    "                 cbar_kws={\"orientation\": \"horizontal\"},\n",
    "                 yticklabels=np.arange(1, p+1), xticklabels=np.arange(1, n+1))\n",
    "ax.set_aspect(\"equal\")\n",
    "plt.title('$B$')\n",
    "plt.yticks(rotation=0)\n",
    "\n",
    "plt.sca(axs[3])\n",
    "plt.title('$=$')\n",
    "plt.axis('off')\n",
    "\n",
    "plt.sca(axs[4])\n",
    "ax = sns.heatmap(C, cmap='RdBu_r', vmax=all_max, vmin=all_min,\n",
    "                 cbar_kws={\"orientation\": \"horizontal\"},\n",
    "                 yticklabels=np.arange(1, m+1), xticklabels=np.arange(1, n+1))\n",
    "ax.set_aspect(\"equal\")\n",
    "plt.title('$C$')\n",
    "plt.yticks(rotation=0)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4f8ed6d9-5aa7-4d98-9faf-7b24072e7fd2",
   "metadata": {},
   "source": [
    "## 矩阵乘法的第二种视角"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "bf786436-36f4-4fdc-8614-0e309c5e969c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-7.30793664e-01,  8.05185036e-01, -1.70406971e-01,\n",
       "        -7.62864552e-01],\n",
       "       [ 3.85438119e-01, -4.24673914e-01,  8.98767269e-02,\n",
       "         4.02353075e-01],\n",
       "       [ 1.93260270e-03, -2.12933260e-03,  4.50645632e-04,\n",
       "         2.01741499e-03],\n",
       "       [-2.02665405e-04,  2.23295794e-04, -4.72576592e-05,\n",
       "        -2.11559379e-04],\n",
       "       [-2.05355600e-01,  2.26259838e-01, -4.78849607e-02,\n",
       "        -2.14367633e-01],\n",
       "       [ 7.06476779e-01, -7.78392806e-01,  1.64736743e-01,\n",
       "         7.37480520e-01]])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "C1 = A[:, [0]] @ B[[0], :]  # 第1列计算结果\n",
    "C1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "af326be7-5237-4d91-a014-2ea161bf76c8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.30197317,  0.05429296,  0.45809088, -0.41073106],\n",
       "       [-0.51564958,  0.09271069,  0.78223629, -0.70136463],\n",
       "       [ 0.46166631, -0.08300482, -0.7003441 ,  0.62793888],\n",
       "       [-0.19335126,  0.03476339,  0.29331231, -0.26298816],\n",
       "       [ 0.46826287, -0.08419085, -0.71035103,  0.63691124],\n",
       "       [ 0.30919658, -0.05559168, -0.46904874,  0.42055604]])"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "C2 = A[:, [1]] @ B[[1], :]  # 第2列计算结果\n",
    "C2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "260da295-7ec2-47d5-8f39-925d830af0a4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.005768  , -0.06169174, -0.04163862,  0.0079445 ],\n",
       "       [ 0.00360515,  0.03855898,  0.02602525, -0.00496553],\n",
       "       [-0.02168576, -0.23194065, -0.15654751,  0.02986872],\n",
       "       [ 0.02844526,  0.304237  ,  0.20534368, -0.03917886],\n",
       "       [-0.01984023, -0.21220172, -0.1432248 ,  0.02732679],\n",
       "       [-0.00448361, -0.04795453, -0.03236674,  0.00617546]])"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "C3 = A[:, [2]] @ B[[2], :]  # 第3列计算结果\n",
    "C3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "6347ba75-481e-4c54-aa53-8527f908c619",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([0.5, 1.5, 2.5, 3.5, 4.5, 5.5]),\n",
       " [Text(0, 0.5, '1'),\n",
       "  Text(0, 1.5, '2'),\n",
       "  Text(0, 2.5, '3'),\n",
       "  Text(0, 3.5, '4'),\n",
       "  Text(0, 4.5, '5'),\n",
       "  Text(0, 5.5, '6')])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 1200x300 with 11 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, axs = plt.subplots(1, 7, figsize=(12, 3))\n",
    "\n",
    "plt.sca(axs[0])\n",
    "ax = sns.heatmap(C1, cmap='RdBu_r', vmax=all_max, vmin=all_min,\n",
    "                 cbar_kws={\"orientation\": \"horizontal\"},\n",
    "                 yticklabels=np.arange(1, m+1), xticklabels=np.arange(1, n+1))\n",
    "ax.set_aspect(\"equal\")\n",
    "plt.title('$C_1$')\n",
    "plt.yticks(rotation=0)\n",
    "\n",
    "plt.sca(axs[1])\n",
    "plt.title('$+$')\n",
    "plt.axis('off')\n",
    "\n",
    "plt.sca(axs[2])\n",
    "ax = sns.heatmap(C2, cmap='RdBu_r', vmax=all_max, vmin=all_min,\n",
    "                 cbar_kws={\"orientation\": \"horizontal\"},\n",
    "                 yticklabels=np.arange(1, m+1), xticklabels=np.arange(1, n+1))\n",
    "ax.set_aspect(\"equal\")\n",
    "plt.title('$C_2$')\n",
    "plt.yticks(rotation=0)\n",
    "\n",
    "plt.sca(axs[3])\n",
    "plt.title('$+$')\n",
    "plt.axis('off')\n",
    "\n",
    "plt.sca(axs[4])\n",
    "ax = sns.heatmap(C3, cmap='RdBu_r', vmax=all_max, vmin=all_min,\n",
    "                 cbar_kws={\"orientation\": \"horizontal\"},\n",
    "                 yticklabels=np.arange(1, m+1), xticklabels=np.arange(1, n+1))\n",
    "ax.set_aspect(\"equal\")\n",
    "plt.title('$C_3$')\n",
    "plt.yticks(rotation=0)\n",
    "\n",
    "plt.sca(axs[5])\n",
    "plt.title('$=$')\n",
    "plt.axis('off')\n",
    "\n",
    "plt.sca(axs[6])\n",
    "ax = sns.heatmap(C, cmap='RdBu_r', vmax=all_max, vmin=all_min,\n",
    "                 cbar_kws={\"orientation\": \"horizontal\"},\n",
    "                 yticklabels=np.arange(1, m+1), xticklabels=np.arange(1, n+1))\n",
    "ax.set_aspect(\"equal\")\n",
    "plt.title('$C$')\n",
    "plt.yticks(rotation=0)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
